package com.openmanus.agent.core;

import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.Map;

/**
 * 智能体单步执行结果
 * 封装智能体每个执行步骤的结果信息
 * 
 * @author OpenManus Team
 * @version 1.0.0
 */
@Getter
@Builder
public class StepResult {

    /**
     * 步骤编号
     */
    private final int stepNumber;

    /**
     * 步骤类型
     */
    private final StepType stepType;

    /**
     * 执行是否成功
     */
    private final boolean success;

    /**
     * 输出内容
     */
    private final String output;

    /**
     * 错误信息
     */
    private final String error;

    /**
     * 是否为终端步骤（完成任务）
     */
    @Builder.Default
    private final boolean terminal = false;

    /**
     * 执行开始时间
     */
    private final LocalDateTime startTime;

    /**
     * 执行结束时间
     */
    private final LocalDateTime endTime;

    /**
     * 额外的元数据
     */
    private final Map<String, Object> metadata;

    /**
     * 步骤类型枚举
     */
    public enum StepType {
        THINKING("思考"),
        TOOL_CALL("工具调用"),
        RESPONSE("响应"),
        ERROR("错误"),
        TERMINATE("终止");

        private final String description;

        StepType(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }

    /**
     * 创建成功的思考步骤结果
     * 
     * @param stepNumber 步骤编号
     * @param output 思考内容
     * @return 思考步骤结果
     */
    public static StepResult thinking(int stepNumber, String output) {
        return StepResult.builder()
            .stepNumber(stepNumber)
            .stepType(StepType.THINKING)
            .success(true)
            .output(output)
            .endTime(LocalDateTime.now())
            .build();
    }

    /**
     * 创建成功的工具调用步骤结果
     * 
     * @param stepNumber 步骤编号
     * @param output 工具执行结果
     * @return 工具调用步骤结果
     */
    public static StepResult toolCall(int stepNumber, String output) {
        return StepResult.builder()
            .stepNumber(stepNumber)
            .stepType(StepType.TOOL_CALL)
            .success(true)
            .output(output)
            .endTime(LocalDateTime.now())
            .build();
    }

    /**
     * 创建成功的工具调用步骤结果（带元数据）
     * 
     * @param stepNumber 步骤编号
     * @param output 工具执行结果
     * @param metadata 元数据
     * @return 工具调用步骤结果
     */
    public static StepResult toolCall(int stepNumber, String output, Map<String, Object> metadata) {
        return StepResult.builder()
            .stepNumber(stepNumber)
            .stepType(StepType.TOOL_CALL)
            .success(true)
            .output(output)
            .metadata(metadata)
            .endTime(LocalDateTime.now())
            .build();
    }

    /**
     * 创建响应步骤结果
     * 
     * @param stepNumber 步骤编号
     * @param output 响应内容
     * @return 响应步骤结果
     */
    public static StepResult response(int stepNumber, String output) {
        return StepResult.builder()
            .stepNumber(stepNumber)
            .stepType(StepType.RESPONSE)
            .success(true)
            .output(output)
            .endTime(LocalDateTime.now())
            .build();
    }

    /**
     * 创建终止步骤结果
     * 
     * @param stepNumber 步骤编号
     * @param output 最终输出
     * @return 终止步骤结果
     */
    public static StepResult terminate(int stepNumber, String output) {
        return StepResult.builder()
            .stepNumber(stepNumber)
            .stepType(StepType.TERMINATE)
            .success(true)
            .output(output)
            .terminal(true)
            .endTime(LocalDateTime.now())
            .build();
    }

    /**
     * 创建错误步骤结果
     * 
     * @param stepNumber 步骤编号
     * @param error 错误信息
     * @return 错误步骤结果
     */
    public static StepResult error(int stepNumber, String error) {
        return StepResult.builder()
            .stepNumber(stepNumber)
            .stepType(StepType.ERROR)
            .success(false)
            .error(error)
            .terminal(true)
            .endTime(LocalDateTime.now())
            .build();
    }

    /**
     * 创建错误步骤结果（带部分输出）
     * 
     * @param stepNumber 步骤编号
     * @param error 错误信息
     * @param output 部分输出
     * @return 错误步骤结果
     */
    public static StepResult error(int stepNumber, String error, String output) {
        return StepResult.builder()
            .stepNumber(stepNumber)
            .stepType(StepType.ERROR)
            .success(false)
            .error(error)
            .output(output)
            .terminal(true)
            .endTime(LocalDateTime.now())
            .build();
    }

    /**
     * 获取执行持续时间（毫秒）
     * 
     * @return 执行持续时间，如果时间信息不完整则返回0
     */
    public long getDurationMillis() {
        if (startTime == null || endTime == null) {
            return 0;
        }
        return java.time.Duration.between(startTime, endTime).toMillis();
    }

    /**
     * 获取元数据值
     * 
     * @param key 键名
     * @return 元数据值
     */
    @SuppressWarnings("unchecked")
    public <T> T getMetadata(String key) {
        if (metadata == null) {
            return null;
        }
        return (T) metadata.get(key);
    }

    /**
     * 检查是否包含指定元数据
     * 
     * @param key 键名
     * @return 是否包含
     */
    public boolean hasMetadata(String key) {
        return metadata != null && metadata.containsKey(key);
    }

    /**
     * 生成步骤摘要
     * 
     * @return 步骤摘要
     */
    public String generateSummary() {
        StringBuilder summary = new StringBuilder();
        summary.append("步骤 ").append(stepNumber).append(" [").append(stepType.getDescription()).append("]: ");
        
        if (success) {
            summary.append("成功");
            if (output != null && !output.isEmpty()) {
                summary.append(" - ").append(output.length() > 100 ? 
                    output.substring(0, 100) + "..." : output);
            }
        } else {
            summary.append("失败");
            if (error != null) {
                summary.append(" - ").append(error);
            }
        }
        
        if (terminal) {
            summary.append(" [终端]");
        }
        
        return summary.toString();
    }

    @Override
    public String toString() {
        return generateSummary();
    }
}
